package com.leyuangame.core.websocket.client;

import com.leyuangame.core.model.Game;
import com.leyuangame.core.model.GamePartion;
import com.leyuangame.core.websocket.handler.BeiMiClient;
import com.leyuangame.core.websocket.handler.RoomInfo;
import com.leyuangame.core.websocket.message.Message;
import com.leyuangame.dao.repository.jpa.GamePartionRepository;
import com.leyuangame.dao.repository.jpa.GameRepository;
import com.leyuangame.utils.UKTools;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Component
public class NettySystemClient implements NettyClient{

    @Autowired
    private GamePartionRepository gamePartionRepository;

    @Autowired
    private GameRepository gameRepository;

	private ConcurrentHashMap<String, BeiMiClient> systemClientsMap = new ConcurrentHashMap<String,BeiMiClient>();
	private ConcurrentHashMap<String, TreeSet<RoomInfo>> waitRoom = new ConcurrentHashMap<String,TreeSet<RoomInfo>>();
	private ConcurrentHashMap<String, RoomInfo> groupRoomClients = new ConcurrentHashMap<String,RoomInfo>();
	public BeiMiClient getClient(String key){
		return  systemClientsMap.get(key);
	}
	
	public void putClient(String token , BeiMiClient client){
		systemClientsMap.put(token, client) ;
		//systemClientsMap.put(client.getSession(), client) ;
	}

	public ConcurrentHashMap<String, BeiMiClient> getSystemClientsMap() {
		return systemClientsMap;
	}

	public void setSystemClientsMap(ConcurrentHashMap<String, BeiMiClient> systemClientsMap) {
		this.systemClientsMap = systemClientsMap;
	}

	public ConcurrentHashMap<String, TreeSet<RoomInfo>> getWaitRoom() {
		return waitRoom;
	}

	public void setWaitRoom(ConcurrentHashMap<String, TreeSet<RoomInfo>> waitRoom) {
		this.waitRoom = waitRoom;
	}

    public ConcurrentHashMap<String, RoomInfo> getGroupRoomClients() {
        return groupRoomClients;
    }

    public void setGroupRoomClients(ConcurrentHashMap<String, RoomInfo> groupRoomClients) {
        this.groupRoomClients = groupRoomClients;
    }

    public void removeClient(String id){
		BeiMiClient beiMiClient = this.getClient(id) ;
		systemClientsMap.remove(id) ;
		if(beiMiClient!=null){
			systemClientsMap.remove(beiMiClient.getUserid()) ;
		}
	}

	public void joinRoom(ChannelContext channelContext, String token, String roomid, String partionid) {
		BeiMiClient beiMiClient = this.getClient(token);
		if(StringUtils.isEmpty(token)&&StringUtils.isEmpty(roomid))
			return;
		if(beiMiClient!=null){
			TreeSet<RoomInfo> roomClients = waitRoom.getOrDefault(roomid,  new TreeSet<RoomInfo>());
			TreeSet<RoomInfo> wait = this.waitRoom.get(partionid);
			Iterator<RoomInfo> it = wait.iterator();
			while (it.hasNext()){
                RoomInfo next = it.next();
                if(next.getRoom_id().equals(roomid)){
                    next.players.add(beiMiClient);
                    Aio.bindGroup(channelContext,beiMiClient.getRoom());
                    channelContext.setAttribute("roomid",roomid);
                    wait.add(next);//重新加入room  排序
                    //向房间内发送人员信息
                    sendRoomInfo(channelContext,next.room_id,next);
                    //如果满员移除wait队列 加入group队列
                    if(next.players.size()==next.getGame().startnumber){
                        this.groupRoomClients.put(roomid,next);
                        it.remove();
                    }
                }
            }
		}
	}

	public void leaveRoom(ChannelContext channelContext,String token, String roomid,String partionid) {
		BeiMiClient beiMiClient = this.getClient(token) ;
        Aio.unbindGroup(beiMiClient.getRoom(),channelContext);
        channelContext.setAttribute("roomid","");
		if(beiMiClient!=null){
            RoomInfo roomInfo = this.groupRoomClients.get(roomid);
            if(roomInfo!=null){
                Iterator<BeiMiClient> it = roomInfo.players.iterator();
                while (it.hasNext()){
                    BeiMiClient next = it.next();
                    if(next.getToken().equals(token)){
                        //向房间内发送人员信息
                        it.remove();
                        sendRoomInfo(channelContext,roomInfo.room_id,roomInfo);
                    }
                }
            }else {//首先从 满房找 若没有在从等待队列找到该玩家room  然后移除
                TreeSet<RoomInfo> roomInfos = this.waitRoom.get(partionid);
                Iterator<RoomInfo> it = roomInfos.iterator();
                while (it.hasNext()){
                    RoomInfo next = it.next();
                    if(next.getRoom_id().equals(roomid)){
                        Iterator<BeiMiClient> it2 = next.players.iterator();
                        while (it2.hasNext()){
                            if(it2.next().getToken().equals(token)){
                                it2.remove();
                                sendRoomInfo(channelContext,next.room_id,next);
                            }
                        }
                    }
                }
            }
        }
	}

    public void beginMatch(ChannelContext channelContext, String token, String partition) {
        BeiMiClient beiMiClient = this.getClient(token) ;
        if(beiMiClient==null)
            return;
        TreeSet<RoomInfo> waitrooms = this.waitRoom.get(partition);

        if(waitrooms==null){
            waitrooms = new TreeSet<>();
            this.waitRoom.put(partition,waitrooms);
            final GamePartion partion = gamePartionRepository.findOne(partition);
            final Game game = gameRepository.findOne(partion.gameid);
            for(int i=0;i<50;i++){
                waitrooms.add(new RoomInfo(game,partion));
            }
        }
        Iterator<RoomInfo> it = waitrooms.iterator();
        while (it.hasNext()){
            RoomInfo next = it.next();
            if(next.players.size()<next.start_number){
                next.players.add(beiMiClient);
                Aio.bindGroup(channelContext,next.getRoom_id());
                channelContext.setAttribute("roomid",next.getRoom_id());
                sendRoomInfo(channelContext,next.room_id,next);
                if(next.players.size()==next.start_number){
                    //满员
                    this.groupRoomClients.put(next.room_id,next);
                    it.remove();
                }
                break;
            }

        }
    }

    public void ready(ChannelContext channelContext, BeiMiClient beiMiClient){
        String roomid = beiMiClient.getRoom();
        RoomInfo roomInfo = null;
        roomInfo = this.groupRoomClients.get(roomid);
        if(roomInfo==null){
            TreeSet<RoomInfo> roomInfos = this.waitRoom.get(roomid);
            for(Iterator<RoomInfo> i = roomInfos.iterator();i.hasNext();){
                RoomInfo next = i.next();
                if(next.getRoom_id().equals(roomid))
                    roomInfo = next;
            }
        }
        boolean begin = true;
        for (BeiMiClient client:roomInfo.players){
            if (client.getToken().equals(beiMiClient.getToken()))
                client.setIsready(0);
            else if(client.getIsready()==1)
                begin = false;
        }
        if(begin==true){
            //TODO 达成开始时间  执行开始逻辑
            switch (roomInfo.game.gamename){
                case "zjh":break;
            }
        }
    }

	public void sendGameEventMessage(String userid, String event, Message data) {
		BeiMiClient beiMiClient = this.getClient(userid) ;
		if(beiMiClient!=null){
			beiMiClient.sendEvent(event, data);
		}
	}

	//发送房间信息
    public void sendRoomInfo(ChannelContext channelContext,String roomid,RoomInfo roomInfo){
        HashMap<String,Object> message = new HashMap<>();
        message.put("roomid",roomInfo.getRoom_id());
        message.put("startnumber",roomInfo.getStart_number());
        message.put("players",roomInfo.getPlayers());
        try {
            Aio.sendToGroup(channelContext.getGroupContext(),roomid, UKTools.convertToTextResponse(message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
